home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
kickstart tools
/
softboot3.31
/
softag.asm
< prev
next >
Wrap
Assembly Source File
|
1996-04-07
|
41KB
|
1,298 lines
*
* SofTag V3.31 -- By Greg Tibbs 10/25/1992
*
* Inspired by ZKick 3.01 by Daniel Zenchelsky
* Assemble with SAS/C 6.00 ASM
*
NOLIST
INCLUDE "exec/types.i"
INCLUDE "exec/tasks.i"
INCLUDE "exec/resident.i"
INCLUDE "exec/execbase.i"
INCLUDE "SoftBoot.i"
LIST
SECTION code
XDEF _TC030
XDEF _Z3cache
XDEF _CRP0
XDEF _CRP1
XDEF _BusErr
XDEF _CatchRom
XDEF _SRP
XDEF @MakeRomTag
XDEF @CachesOff
XDEF @SF_Supervisor
XDEF _LogRomStart
XDEF _PhyRomStart
XDEF @JTRom
XDEF @MyColdReboot
XDEF @SpeedRom
XDEF @GetCPUType
XDEF @GetTC040
XDEF @GetTC030
XDEF @KillRomTags
XDEF _NumMemAreas
XDEF _MemListArray
XDEF @JTRom13030
XDEF @MakeRomTag13
XDEF _IDCpu
XDEF @ForceTTX
XREF _LVOSupervisor
XREF _LVODisable
XREF _LVOSuperState
XREF _LVOAllocAbs
XREF _LVOEnable
XREF _LVOSumKickData
XREF _LVOSetFunction
VERSION: EQU 3
REVISION: EQU 31
MYPRI EQU 127
_LVOColdReboot EQU -726
ABSEXECBASE EQU (4)
CNOP 0,4
;-----------------------------------------------------------------------
; From here on is protected from erasure during reboot
;-----------------------------------------------------------------------
; 128 byte Buffer Area in case of AllocMem Memlist tail overwrite!
_SaveMem:
DC.L 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0
KickMem: ;Area for KickMemList data
DC.L 0,0,0,0
_MemListArray DC.L 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0
KickTag:
DC.L initDDescrip
DC.L 0 ;Next Romtag initDescrip Pointer
_CRP0: DC.L $7fff0002
_CRP1: DC.L 0
_TC030: DC.L $80f0d400
_SRP: DC.L 0
_PhyRomStart: DC.L 0
_LogRomStart: DC.L $00f80000
_BusErr: DC.L 0
_CatchRom: DC.L 0
_Z3cache DC.L 1
_NumMemAreas: DC.L 3
ROMColdReboot: DC.L 0
Zero: DC.L 0
DC.L 0
;-----------------------------------------------------------------------
; A romtag structure. Both "exec" and "ramlib" look for
; this structure to discover magic constants about you
; (such as where to start running you from...).
;-----------------------------------------------------------------------
; Most people will not need a priority and should leave it at zero.
; the RT_PRI field is used for _configuring the roms. Use "mods" from
; wack to look at the other romtags in the system
initDDescrip:
; STRUCTURE RT,0
DC.W RTC_MATCHWORD ; UWORD RT_MATCHWORD
DC.L initDDescrip ; APTR RT_MATCHTAG
DC.L _EndTag ; APTR RT_ENDSKIP
DC.B RTF_COLDSTART ; UBYTE RT_FLAGS
DC.B VERSION ; UBYTE RT_VERSION
DC.B NT_UNKNOWN ; UBYTE RT_TYPE
DC.B MYPRI ; BYTE RT_PRI
DC.L modName ; APTR RT_NAME
DC.L idString ; APTR RT_IDSTRING
DC.L _InitRoutine ; APTR RT_INIT
; this is the name that the module will have
modName: DC.B 'SoftBoot.romtag ',0
idString: DC.B 'SoftBoot.romtag 3.31 (10/25/92)',13,10,0
CNOP 0,4
_InitRoutine:
movem.l d0-d7/a0-a6,-(a7) ;Save Registers
move.l ABSEXECBASE,a6 ;Get Execbase
;
; The following code protects the ROM by allocating its RAM image
; at 7f80000. Normally this would be done in the KickMemList,
; but 2.0 has a wonderful feature that if it detects a 68030CPU
; with its MMU on at boot time, it will autoallocate that area,
; causing the kickmemlist allocation to fail. By using the ROM at
; the same address and not caring whether or not the AllocABs
; passes or fails, similar memory models can be had for the
; 68040 CPU as well as the 030. This is all done for the nice
; feature of making RAD work when switching CPUs. This risks
; another romtag allocating something in this area, so the
; priority has been increased to the maximum of 127. If some
; future OS takes away the autoallocate SuperKickstart 'feature',
; the current code will continue to work. It also pushes the
; Largest memory fragment to the end of A3000 motherboard RAM,
; reducing memory clutter.
;
; The following code also allocates the 16 bytes in front of the
; ROM to prevent a MemList tail from overwriting it. That allocation
; will also overwrite the first two long words, so they are copied to
; the stack and restored after the allocation.
;
move.l #$7f80000,a0 ;Ram Address of Start of Rom
move.l (a0)+,a2 ;Get 1st Long Word
move.l (a0)+,a3 ;Get 2nd Long word
movem.l a2-a3,-(a7) ;Save on stack
moveq #$10,d0 ;Number of bytes ahead of ROM to protect
move.l #$7f7fff0,a1 ;Address to allocate
jsr _LVOAllocAbs(a6)
move.l #$80000,d0 ;# of bytes to allocate in ROM
move.l #$7f80000,a1 ;Rom Address
jsr _LVOAllocAbs(a6) ;If fails, 2.0 must have already allocated
; this area for me - how nice! thumppp!
movem.l (a7)+,a2-a3 ;Fix MemList tail overwrite of 1st two Rom
move.l #$7f80000,a0 ; long words
move.l a2,(a0)+ ;Restore 2nd Longword of ROM
move.l a3,(a0)+ ;Restore 1st Longword of ROM
;
; Now take over ColdReboot() so My MMU tables will be loaded at a software reset
;
jsr SFColdReboot
;
; Now Check CPU and handle if a reboot or a pass thru, if a particular
; CPU does not have MMU tables setup, then it will pass thru, although
; MMU tables for the other CPU will continue to be protected if they
; were ever generated in the first place.
;
btst.b #AFB_68040,ATNFLGS(a6)
beq.b Do030 ;Jump to next test if not 040
move.l _SRP,d0 ;Test if 040 MMU tables are setup
cmpi.l #0,d0 ;No MMU tables if SRP = 0
beq.b ExitInit
lea.l My040InitCode,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
bra.b ExitInit ;Return to OS
Do030:
btst.b #AFB_68030,ATNFLGS(a6) ;Test for 030
bne.b Ok030
btst.b #AFB_68020,ATNFLGS(a6) ;Test for 020 (851 assumed)
beq.b ExitInit ;Just return if not a 020 or better
Ok030:
move.l _CRP1,d0 ;Test if 030/020&851 MMU tables are setup
cmpi.l #$0,d0 ;No MMU tables if CRP = 0
beq.b ExitInit
lea.l My030InitCode,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
ExitInit:
movem.l (a7)+,d0-d7/a0-a6 ;Restore Registers
rts ;Return to OS
My030InitCode:
bsr SetMMU030 ;This Must be called for the hardware reset conditon
btst.l #31,d1
beq Reboot ;MMU off, turn on to initial state and reboot
rte
;Load Exception handler and take care of Software and Hardware reset conditions
SetBusErrorHandler:
move.l _BusErr,d0 ;Check if we want to disable Bus Errors
cmpi.l #0,d0
beq.b DoneBus ;Branch if non zero
move.b #0,($DE0000) ;Set Buster to no Bus Error time out
DoneBus:
move.l _CatchRom,d0 ;load and test Error Handler Bypass
cmpi.l #0,d0
bne.b SBEHend
_MOVEC vbr,d0 ;Get VBR. Should be zero, but never know
move.l d0,a0
move.l $8(a0),a1 ;Get Old Bus Error Handler Address
move.l a1,OH1 ;Store it
lea.l _BusErrorHandler,a1 ;Get new handler address
move.l a1,$8(a0) ;Write to exception table
move.l a1,8 ;Write to address 8 for good measure
SBEHend:
rts
My040InitCode:
bsr SetBusErrorHandler
bsr SetMMU ;This Must be called for the hardware reset conditon
cmpi.l #0,d1
beq Reboot ;MMU off, turn on to initial state and reboot
;Change Cache code for Fast Ram
_CPUSHA040 ;Dump Caches to RAM
_PFLUSHA040 ;Clear ATC
_CINVA040 ;Invalidate caches - Note SetMMU cleared cacr
move.l _Z3cache,d1 ; if d1 is non-zero, turn on dttx copyback mode
cmpi.l #0,d1
beq BypassMMU ; Zero, therefore leave dttx as is
move.l #$08f7c020,d0 ;Turn on Copyback mode for data acesses
_MOVEC d0,dtt1
move.l #$04fbc020,d0
_MOVEC d0,dtt0
_PFLUSHA040 ;Kill ATC and Caches again for extra good measure
_CINVA040
BypassMMU:
rte
Reboot:
nop
move.l _LogRomStart,a0
adda.l #2,a0
bra LongAddr1
CNOP 0,4
LongAddr1:
reset
jmp (a0)
SetMMU:
_MOVEC tc,d1 ;Move Get Translation Control Register
cmpi.w #$0,d1 ;Test if MMU is already on
bne mmu_on ;if so, bypass and return with TC contents
; as status
SetMMU1:
moveq #0,d1 ;Clear out VBR, TC, and CACR
_MOVEC d1,vbr
SetMMU2:
_MOVEC d1,tc
_MOVEC d1,cacr
_CPUSHA040 ;Dump Caches
_PFLUSHA040 ;Clear out ATC
_CINVA040 ;Invalidate caches
move.l _SRP,d1 ;Write MMU Root table pointer to SRP & URP
_MOVEC d1,srp
_MOVEC d1,urp
move.l #$04fbc040,d1 ;Set up MMU for default memory translation setup
_MOVEC d1,dtt0
move.l #$08f7c040,d1
_MOVEC d1,dtt1
move.l #$04fbc000,d1
_MOVEC d1,itt0
move.l #$08f7c000,d1
_MOVEC d1,itt1
_CPUSHA040 ;Dump and Kill caches once again
_PFLUSHA040
_CINVA040
move.w #$C000,d0 ;Load TC (8K tables)
_MOVEC d0,tc ; Activate TC
move.l #0,d1 ;Return code for testing if MMU was on at
;Start of SetMMU - 0 indicates it was off
mmu_on:
rts
SetMMU030:
lea.l StackCopy,a0 ;Clear tc
_PMOVE tc,(a0) ;Save Translation Control Register
move.l StackCopy,d1 ;Load it back from Ram
btst.l #31,d1 ;Test if MMU is already on
bne mmu_on030 ;if so, bypass and return with TC contents
; as status
SetMMU031:
moveq #0,d1 ;Clear out VBR, TC, and CACR
_MOVEC d1,vbr
SetMMU032:
lea.l Zero,a0 ;Clear TC and cacr
_PMOVE (a0),tc
move.l #$0808,d1
_MOVEC d1,cacr ;Turn off & dump Data and Instruction Caches
lea.l _CRP0,a0 ;Write MMU Root table pointer to SRP & URP
_PMOVE (a0),crp
lea.l _TC030,a0 ;Load TC and activate the MMU
_PMOVE (a0),tc
move.l #0,d1 ;Return code for testing if MMU was on at
;Start of SetMMU - 0 indicates it was off
mmu_on030:
rts
; Crude way of handling invalid and write access errors,
; all others will be sent to guru land via CBM's handler
CNOP 0,4 ;Align Stack
StackCopy:
dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
_BusErrorHandler:
move.l a5,SafeA5 ;Save on end of temporary stack
lea.l _TempStack,a5 ;New Temporary storage area
movem.l d0-d2/a0-a2,-(a5) ;Save minimal registers
move.l a7,a0 ;Copy the Stack Frame for Later Perusal
lea.l StackCopy,a1
moveq #14,d0 ;Do 15 times (does a copy on d0 = 0 count)
SCL:
move.l (a0)+,(a1)+
dbra d0,SCL
move.w $c(a7),d0 ;Get Special Status Word
move.l d0,d1 ;Save it for other tests
btst.l #10,d0 ;Check for ATC fault
beq.w BusError ;Not an ATC fault - Probably a Bus Error
andi.l #$18,d0 ;Check for TT=$0
bne.w NotNormal ;Not a Data Access Error
andi.l #5,d1 ;Mask TM field from SSW
cmpi.l #5,d1 ;Check TM=$5
beq.b DoWB1 ;Supervisor, jump
cmpi.l #1,d1 ;Check TM=$1 (User)
bne.w NotNormal ;Again, Not a data access error
;We are an ATC Invalid access or
; write fault error
DoWB1:
move.l $2C(a7),d2 ;Get WB1D
move.l $28(a7),a2 ;Get WB1A
move.w $12(a7),d0 ;Get WB1S
btst.l #7,d0 ;Valid Write?
beq.b DoWB2
bsr WriteBack1 ;Perform WriteBack1
DoWB2:
move.l $24(a7),d2 ;Get WB2D
move.l $20(a7),a2 ;Get WB2A
move.w $10(a7),d0 ;Get WB2S
btst.l #7,d0 ;Valid Write?
beq.b DoWB3
bsr WriteBack ;Perform WriteBack2
DoWB3:
move.l $1c(a7),d2 ;Get WB3D
move.l $18(a7),a2 ;Get WB3A
move.w $e(a7),d0 ;Get WB3S
btst.l #7,d0 ;Valid Write?
beq.b Done
bsr WriteBack ;Perform WriteBack3
Done:
movem.l (a5)+,d0-d2/a0-a2 ;Restore Registers
move.l SafeA5,a5
rte ;Return from exception
BusError: ;Routine to handle Bus Errors via Exceptions
;Under Construction
NotNormal:
movem.l (a5)+,d0-d2/a0-a2 ;Restore Registers
move.l SafeA5,a5
dc.w $4ef9
OH1: dc.l $0 ;jmp (OldHandler) - Address filled in
; by SetupBusErrorHandler()
WriteBack: ;At this point we only care about the
;load Fault Address (jsr adds 4 to stack offset)
move.l $18(a7),a1
cmpa.l a2,a1 ;Compare against WBXA
beq.b NotDo ;Return if same-We don't want another fault!
andi.l #$60,d0 ;Mask off Size + check for Longword
beq.b LongWord ;Yep, LongWord
cmpi.w #$20,d0 ;Check for Byte access
beq.b Byte ;Yep, Byte
cmpi.w #$40,d0 ;Check for Word Access
bne.b Line ;Nope, 16 Byte Line Access
Word:
move.w d2,(a2) ;Perform Word Write
NotDo:
rts
LongWord:
move.l d2,(a2) ;Perform Long word write
rts
Byte:
move.b d2,(a2) ;Perform Byte Write
rts
Line:
addq.l #4,A7 ;I can't handle a line error here so I
bra NotNormal ; punt and run CBM's handler (guruland)
;--------------------------------------------------------------------------------
;WriteBack1 handler for WB1X 68040 Access Error stack frame, Test code
;A0 unaltered
;WB1A in A2, WB1D in D2, WB1S in D0. D0,D1 & A1 are destroyed by the code
;-------------------------------------------------------------------------------
WriteBack1:
;TT=0 Already tested for!
move.l $18(a7),a1 ;Load Fault Address from Stack frame
cmpa.l a2,a1 ;Compare against WB1A
beq.w W1End ;Return if same-We don't want another fault!
move.b d0,d1 ;Copy WB1S for trashing
andi.b #$18,d1 ;Mask off TT field of WB1S
beq.w W1End ;Jump if not Normal Access Type
move.l a2,d1 ;Copy Dest Address
andi.l #3,d1 ;Get last two address bits
move.l d1,a1 ;Save for Later
andi.l #$60,d0 ;Mask off Size + check for Longword
beq.w W1LongWord ;Yep, LongWord
cmpi.b #$20,d0 ;Check for Byte access
beq.w W1Byte ;Yep, Byte
cmpi.b #$40,d0 ;Check for Word Access
bne.w W1Line ;Nope, 16 Byte Line Access
W1Word: ;If not one of above, must be Word
cmpa.l #0,a1 ;Check if WB1A Address is xxxxxx00
bne.b WA1
WA0:
moveq #16,d1 ;Shift data right to fit d15:d0
ror.l d1,d2
move.w d2,(a2) ;Write Word to Address
bra.b W1End ;Done
WA1:
cmpa.l #1,a1 ;Check if WB1A Address is xxxxxx01
bne.b WA2
moveq #8,d1 ;Shift data right to fit D15:0
ror.l d1,d2 ; instead of D23:8
move.w d2,(a2) ;Write word to address
rts ;Done
WA2:
cmpa.l #2,a1 ;Check if WB1A address is xxxxxx10
bne.b WA3
move.w d2,(a2) ;Data register aligned OK, Write Word
rts ;Done
WA3:
cmpa.l #3,a1 ;Check if WB1A address is xxxxxx11
bne.b W1End ;Something wrong if not == 3!
moveq #8,d1 ;Shift data from 7:0,31:24 to 15:0
rol.l d1,d2
move.w d2,(a2) ;Perform Byte Write
W1End:
rts
W1LongWord:
cmpa.l #0,a1 ;Check if WB1A is xxxxxx00
bne.b LA1
LA0:
move.l d2,(a2) ;Everything aligned, write long word
rts ;Done
LA1:
cmpa.l #1,a1 ;Check if WB1A is xxxxxx01
bne.b LA2
moveq #8,d1 ;Rotate left to align data from 23:0,31:24
ror.l d1,d2 ; to 31:0
move.l d2,(a2) ;Perform long word write
rts ;Done
LA2:
cmpa.l #2,a1 ;Check if WB1A is xxxxxx10
bne.b LA3
moveq #16,d1 ;Rotate from 15:0,31:16 to 31:0
ror.l d1,d2
move.l d2,(a2) ;Perform long word write
rts ;Done
LA3:
cmpa.l #3,a1 ;Check if WB1A is xxxxxx11
bne.b LAEnd ;Something wrong if not!
moveq #8,d1 ;Rotate from 7:0,31:8 to 31:0
rol.l d1,d2
move.l d2,(a2) ;Perform long word write
LAEnd:
rts
W1Byte: ;a0 contains WB1A, a1 is masked WB1A, d2 = WB1D
cmpa.l #0,a1 ;Check if WB1A is xxxxxx00
bne.b BA1
BA0:
moveq #8,d1 ;Rotate from 31:24 to 7:0
rol.l d1,d2
move.b d2,(a2) ;Perform Byte Write
rts ;Done
BA1:
cmpa.l #1,a1 ;Check if WB1A is xxxxxx01
bne.b BA2
moveq #16,d1 ;Rotate from 23:16 to 7:0
ror.l d1,d2
move.b d2,(a2) ;Perform Byte Write
rts ;Done
BA2:
cmpa.l #2,a1 ;Check if WB1A is xxxxxx10
bne.b BA3
moveq #8,d1 ;Rotate from 15:8 to 7:0
ror.l d1,d2
move.b d2,(a2) ;Perform Byte Write
rts
BA3:
cmpa.l #3,a1 ;Check if WB1A is xxxxxx11
bne.b BAEnd
move.b d2,(a2) ;Perform Byte Write - Alignment ok
BAEnd:
rts
W1Line:
addq.l #4,a7 ;I can't handle a line error here, so I
bra NotNormal ;punt and run CBM's handler (guruland)
;
; SFColdReboot is required to ensure my MMU tables are loaded prior to reboot.
;
SFColdReboot:
movem.l d0-d7/a0-a6,-(a7) ;Save Registers
move.l ABSEXECBASE,a6 ;ensure ExecBase is in a6
movea.l a6,a1 ;Library for SetFunction to operate on
lea.l NewColdReboot,a0 ;Address of replacement routine in a0
move.l a0,d0 ;move address to d0
lea.l _LVOColdReboot,a0 ;Load library offset into a0
jsr _LVOSetFunction(a6) ;Perform the Setfunction
move.l d0,ROMColdReboot ;Save Old Vector
movem.l (a7)+,d0-d7/a0-a6 ;Restore registers
rts
;NewColdReboot restores the MMU for the 030 or 040 as other people's MMU
; tools may have taken over. For guranteed ROM replacement, this code
; will jam the original SRP/URP for the 040 and CRP0 & CRP1 for the 030.
NewColdReboot:
btst.b #AFB_68040,ATNFLGS(a6)
beq.b ResetTest030 ;Jump to next test if not 040
lea.l My040ResetCode,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
rts ;We won't return here
ResetTest030:
btst.b #AFB_68030,ATNFLGS(a6) ;Test for 030
bne.b Reset030
btst.b #AFB_68020,ATNFLGS(a6) ;Test for 020 (851 assumed)
beq.b NOMMUResetCode ;Run RomColdReboot if not a 020 or better
Reset030:
lea.l My030ResetCode,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
rts ;We will Never Return here
NOMMUResetCode:
lea.l ROMColdReboot,a0 ;Load Old Reset Vector
jmp (a0) ;Reboot Machine
;Never get back here!
rts ;Not needed, but here for safety
My040ResetCode:
moveq #0,d1 ;0 clears out TC etc in SetMMU2
jsr SetMMU2 ;Turn on 040 MMU
bra Reboot ;Reboot
rte ;Will Never Return
My030ResetCode:
jsr SetMMU032 ;Turn on 030 MMU
bra Reboot ;Reboot
;Will Never Return
rte ;Not Needed, but just to be safe
CNOP 0,4 ;LongWord align stack
DC.L 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
_TempStack: DC.L $0
SafeA5: DC.L $0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Buffer for overwrites
_EndTag:
;--------------------End of Protected Romtag Space-------------------------------
@CachesOff:
movem.l d0-d7/a0-a6,-(sp) ;Save Registers
move.l ABSEXECBASE,a6 ;Load Execbase
btst.b #AFB_68040,ATNFLGS(a6)
beq.b CS030 ;Don't mess with anything if not 040
CS040:
lea.l CachesOff040,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
bra COExit
CS030:
lea.l CachesOff030,a5
jsr _LVOSupervisor(a6)
COExit:
movem.l (a7)+,d0-d7/a0-a6 ;Restore Registers
rts ;Return to OS
CachesOff030:
move.l #$0808,d1
_MOVEC d1,cacr ;Turn off & dump Data and Instruction Caches
rte
CachesOff040:
moveq #0,d1
_MOVEC d1,cacr
_CPUSHA040 ;Dump Caches
_PFLUSHA040 ;Clear out ATC
_CINVA040 ;Invalidate caches
rte
;
; SF_Supervisor is required because when OVRMMU option is used, the previous
; ROM could be in RAM, and in particular, the new ROM will probably overwrite
; the contents of the old, invalidating all library LVOs. Thus, Supervisor
; must be setfunctioned to prevent MakeRomTag, JTROM, JTROM13030 et.al from
; going blooey only for the duration it takes to move the rom and reboot.
; Supervisor is not Setfunctioned unless the rom is to be overwritten and a
; new OS loaded!
;
; Note - the calling 'C' code must Disable() before calling this routine!
;
@SF_Supervisor:
movem.l d0-d7/a0-a6,-(a7) ;Save Registers
move.l ABSEXECBASE,a6 ;ensure ExecBase is in a6
;By being in Supervisor mode before
;the SetFunction(), it prevents a privlege
;exception from occuring until I can mash
;down my vector immediately after SetFunction()
jsr _LVOSuperState(a6)
movea.l a6,a1 ;Library for SetFunction to operate on
lea.l MySupervisor,a0 ;Address of replacement routine in a0
move.l a0,d0 ;move address to d0
lea.l _LVOSupervisor,a0 ;Load library offset into a0
jsr _LVOSetFunction(a6) ;Perform the Setfunction
lea.l MyExcepHndlr,a1 ;Address of Privlege violation handler
_MOVEC vbr,d0 ;Get vbr
move.l d0,a0 ;Move to address register
move.l a1,$20(a0) ;Write to exception table
move.l a1,$20 ;Write to address $20 for good measure
andi #$fdff,sr ;Go back to User mode
movem.l (a7)+,d0-d7/a0-a6
rts
MySupervisor: ;This routine is relocatable
ORI.W #$2000,SR ;In user mode, creates exception #8 and
;control never returns to here
;If already in Supervisor mode, pass thru
SUBQ.L #8,SP ;Reduce the Stack pointer to create space for
;a simulated exception frame $0, so the user's
;RTE will run the desired instruction without
;messing up his stack!
MOVE.W SR,(SP) ;Push the current SR onto the stack so after
;the user code's RTE, SR will be loaded from
;stack and we will still be in Supervisor mode.
MOVE.L A0,SV1 ;Save A0
LEA.L MyRTS,A0 ;Load address of RTS
MOVE.L A0,2(SP) ;Change the Return address, so an RTS will be
;run to exit the Supervisor() function
MOVEA.L SV1,A0 ;Restore A0
MOVE.W #$20,6(SP) ;Write Privilege exception vector code (frame
;format $0) to complete exception fake
JMP (A5) ;Jump to User code
MyExcepHndlr: ;The address of this routine must be written
;to vbr+$20
MOVE.L A0,SV1 ;SAVE A0 as we need it for address comparisons
LEA.L MySupervisor,A0 ;Get Address of opcode which might have caused
;the exception
CMPA.L 2(SP),A0 ;Check address of the instruction which created
;the exception
BNE.W Reboot ;It wasn't from Supervisor(), so jump to Reboot
LEA.L MyRTS,A0 ;Load Address of RTS into A0
MOVE.L A0,2(SP) ;Change value of return address on the stack
;so that Supervisor() will RTS immediately
;after the RTE
MOVEA.L SV1,A0 ;Restore A0
JMP (A5) ;Perform User's code, his RTE will return
;from the exception to the following RTS
MyRTS: RTS ;Return from the Supervisor() function
SV1: DC.L 0
@JTRom: ;Jump To MMUed Rom
move.l ABSEXECBASE,a6 ;Load Execbase
lea.l JTSRom,a5
jsr _LVOSupervisor(a6) ;In Supervisor state when you jump to ROM
rts ; Should never get here!!!
JTSRom:
move.l ABSEXECBASE,a6 ;Load Execbase
btst.b #AFB_68040,ATNFLGS(a6)
beq.b JTRom030 ;Don't mess with anything if not 040
bsr SetMMU1 ;Turn MMU on and set up default MMU state
bra Reboot
JTRom030: ;Jump To MMUed Rom
bsr SetMMU031 ;Turn MMU on and set up default MMU state
bra Reboot ;jump to longword aligned routine
@MakeRomTag:
movem.l d0-d7/a0-a6,-(a7) ;Setup romtag in memory
move.l ABSEXECBASE,a6 ;Get execbase
lea.l KickMem+14,a0 ;Set up KickMemPtr
move.l _NumMemAreas,d0 ;Variable length number of ram areas
move.l d0,d1
addq.l #1,d0 ;Add extra to romtag list
move.w d0,(a0)+ ; to KickMemList
lsl #3,d1 ;8 bytes per memory entry
adda.l d1,a0 ;Point to End of List
lea.l _SaveMem,a1
move.l a1,(a0)+ ;Add Romtag Allocation Start
lea.l _EndTag-_SaveMem,a1
move.l a1,(a0)+ ;Add Romtag Allocation Length
lea.l KickMem,a0
move.l KickMemPtr(a6),(a0) ;old pointer in ln_Succ
move.l a0,KickMemPtr(a6)
;
; Set up KickTagPtr
;
lea KickTag,a0
move.l KickTagPtr(a6),4(a0) ;Old pointer at the end of the table
beq.s .nomore
bset.b #7,4(a0) ;Bit 31 = Extend table
.nomore:
move.l a0,KickTagPtr(a6)
;
; Calculate checksum
;
jsr _LVOSumKickData(a6)
move.l d0,KickCheckSum(a6)
movem.l (a7)+,d0-d7/a0-a6
rts
@MyColdReboot: ;KILLROM function
move.l ABSEXECBASE,a6 ;Get Execbase
jsr _LVODisable(a6)
jsr _LVOSuperState(a6) ;Goto Supervisor mode
moveq #0,d0
move.l d0,$7fc5000 ;Blow Away 1.3 Romtag
move.l d0,$6a0
jsr _IDCpu
btst.l #AFB_68040,d0
beq.b ColdReboot030 ;Don't mess with anything if not 040
bsr SetMMU ;Setup MMU to default
moveq #0,d0 ;Turn off MMU (SetMMU turned it on)
_MOVEC d0,tc
_CPUSHA040
_PFLUSHA040
_CINVA040
bra.b CommonReboot
ColdReboot030:
bsr SetMMU030 ;Setup MMU to default
lea.l Zero,a0
_PMOVE (a0),tc
CommonReboot:
moveq #0,d0
_MOVEC d0,cacr
moveq #$52,d1 ;Number of longwords to kill
move.l d0,(a6) ;blow away exec!
tloop:
move.l d0,(a6)+ ;kill area above execbase
dbra d1,tloop
moveq #0,d0
moveq #$52,d1
tloop1:
move.l d0,-(a6) ;Kill area below execbase
dbra d1,tloop1
clr.l ColdCapture(a6)
clr.l CoolCapture(a6)
clr.l WarmCapture(a6) ;Clear vectors and reboot
clr.l KickTagPtr(a6)
clr.l KickMemPtr(a6)
bra Reboot
@KillRomTags:
move.l d0,-(a7) ;Push d0
move.l #0,d0 ;Load Zero
move.l d0,initDDescrip ;Kill Romtag header 2.0+
move.l d0,initDDescrip2 ;Kill Romtag header 1.3
move.l (a7)+,d0 ;Pop d0
rts ;Return
;--------------------------------------------------------------------------------
; Note: FastRom is not recoverable due to when program exits, romtag and Bus Error
; Handler are susceptible to getting overwritten. So it was chosen not to load
; the romtag into exec, and to have the setup die on reset. Because of this the
; NoCatchRom option is ignored when entered with the Fastrom parameter. Bus
; error generation (NOBUSERRORS option) is settable in Fastrom.
;---------------------------------------------------------------------------------
@SpeedRom:
movem.l d0-d7/a0-a6,-(a7) ;Save Registers
move.l ABSEXECBASE,a6 ;Load Execbase
cmpi.w #36,LIB_VERSION(a6)
blt.b SRExit ;1.3 we are already in MMU!
btst.b #AFB_68040,ATNFLGS(a6)
beq.b _SpeedRom030 ;Don't mess with anything if not 040
lea.l SpeedCode,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
SRExit:
movem.l (a7)+,d0-d7/a0-a6 ;Restore Registers
rts ;Return to OS
SpeedCode:
move.l _BusErr,d0 ;Check if we want to disable Bus Errors
cmpi.l #0,d0
beq.b DoneBus2 ;Branch if non zero
move.b #0,($DE0000) ;Set Buster to no Bus Error time out
DoneBus2:
moveq #0,d1 ;Bypass clearing VBR in SetMMU
bsr SetMMU2 ;Set up MMU
_CPUSHA040 ;MMU will be on at this time, this code is sensitive
_PFLUSHA040 ; to what the previous mttx registers were. In particular,
_CINVA040 ; The area representing the area that this code resides
; in must be adjusted such that it doesn't go 'away'.
move.l _Z3cache,d1 ;if d1 is non-zero, turn on dttx copyback mode
cmpi.l #0,d1
beq BypassMMU2 ; Zero, therefore leave dttx as is
move.l #$08f7c020,d0 ;Setup Ram for Copyback cacheable
_MOVEC d0,dtt1 ; Had to be previously noncacheable, nonserialized
move.l #$04fbc020,d0 ; for OS memory determination.
_MOVEC d0,dtt0
_CPUSHA040
_PFLUSHA040 ;Flush ATC to make sure changes don't mess up anything
_CINVA040 ;Dump D & I caches for good measure
BypassMMU2:
move.l #$80008000,d1
_MOVEC d1,cacr ;Turn on Data and Instruction Caches
rte
_SpeedRom030:
lea.l SpeedCode030,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
movem.l (a7)+,d0-d7/a0-a6 ;Restore Registers
rts ;Return to OS
SpeedCode030:
bsr SetMMU032 ;Set up MMU
move.l #$2111,d1
_MOVEC d1,cacr ;Turn on Data and Instruction Caches
rte
@ForceTTX: ;Turn on nttx registers
movem.l d0-d1/a5-a6,-(a7) ;Save d0 & d1 & a5 - a6
move.l ABSEXECBASE,a6 ;Get Execbase
lea.l ResetTTX,a5 ;Load code pointer
jsr _LVOSupervisor(a6) ;Run code in Supervisor Mode
movem.l (a7)+,d0-d1/a5-a6 ;Restore d0 & d1
rts
ResetTTX:
_MOVEC tc,d0 ;Save tc
move.l #0,d1
_MOVEC d1,tc ;Turn tc off
_CPUSHA040 ;Dump and Kill caches
_PFLUSHA040
_CINVA040
move.l _Z3cache,d1 ;if d1 is non-zero, turn on dttx copyback mode
cmpi.l #0,d1
beq BypassMMU3 ;Zero, therefore leave dttx as is
move.l #$04fbc020,d1 ;Set up MMU for default memory translation setup
_MOVEC d1,dtt0
move.l #$08f7c020,d1
_MOVEC d1,dtt1
bra DoIttx
BypassMMU3:
move.l #$04fbc040,d1 ;Set up MMU for default memory translation setup
_MOVEC d1,dtt0
move.l #$08f7c040,d1
_MOVEC d1,dtt1
DoIttx:
move.l #$04fbc000,d1
_MOVEC d1,itt0
move.l #$08f7c000,d1
_MOVEC d1,itt1
_CPUSHA040 ;Dump and Kill caches once again
_PFLUSHA040
_CINVA040
_MOVEC d0,tc ;Turn tc back on
rte
@GetTC040:
movem.l d1-d7/a0-a6,-(a7)
move.l ABSEXECBASE,a6 ; Get ExecBase
lea 5$,a5 ; Get the start of the supervisor code
jsr _LVOSupervisor(a6)
movem.l (a7)+,d1-d7/a0-a6
rts
5$
_MOVEC tc,d0
rte
@GetTC030:
movem.l d1-d7/a0-a6,-(a7)
move.l ABSEXECBASE,a6 ; Get ExecBase
subq.l #4,sp ; Make a place to dump TC
move.l sp,a0
lea 2$,a5 ; Get the start of the supervisor code
jsr _LVOSupervisor(A6)
move.l (sp),d0 ; Here's the result
addq.l #4,sp
movem.l (a7)+,d1-d7/a0-a6
rts
2$
_PMOVE tc,(a0)
rte
@GetCPUType:
movem.l a4-a6,-(sp) ; Save this register
move.l ABSEXECBASE,a6 ; Get ExecBase
btst.b #AFB_68040,ATNFLGS(a6) ; Does the OS think an '040 is here?
beq 0$
move.l #68040,d0 ; Sure does...
movem.l (sp)+,a4-a6
rts
0$ btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here?
beq 10$
move.l #68030,d0 ; Sure does...
movem.l (sp)+,a4-a6
rts
10$ btst.b #AFB_68020,ATNFLGS(a6) ; Does the OS think an '020 is here?
beq 20$
move.l #68020,d0 ; Sure does...
movem.l (sp)+,a4-a6
rts
20$ moveq #0,d0 ; Not an '040
movem.l (sp)+,a4-a6
rts
@JTRom13030:
jmp $7fc000c ;init routine in 1.3 Bonus
CNOP 0,4
;-----------------------------------------------------------------------
; From here on is protected from erasure during reboot
;-----------------------------------------------------------------------
;-----------------------------------------------------------------------
; A romtag structure. Both "exec" and "ramlib" look for
; this structure to discover magic constants about you
; (such as where to start running you from...).
;-----------------------------------------------------------------------
; Most people will not need a priority and should leave it at zero.
; the RT_PRI field is used for _configuring the roms. Use "mods" from
; wack to look at the other romtags in the system
initDDescrip2:
; STRUCTURE RT,0
DC.W RTC_MATCHWORD ; UWORD RT_MATCHWORD
DC.L initDDescrip2 ; APTR RT_MATCHTAG
DC.L _EndTag2 ; APTR RT_ENDSKIP
DC.B RTF_COLDSTART ; UBYTE RT_FLAGS
DC.B VERSION ; UBYTE RT_VERSION
DC.B NT_UNKNOWN ; UBYTE RT_TYPE
DC.B MYPRI ; BYTE RT_PRI
DC.L modName2 ; APTR RT_NAME
DC.L idString2 ; APTR RT_IDSTRING
DC.L _InitRoutine2 ; APTR RT_INIT
CNOP 0,4
;
; It is assumed that _InitRoutine will only be run under 1.3 as
; it is mapped into f05xxx by the 1.3 MMU routine. Since 2.0
; requires a kicktag pointer for non-fxxxxx romtags, it should
; not be found and executed under 2.0. Under 1.3, it will install
; the ColdInit routine as the ColdCapture vector. Should the
; System be hardware rebooted via keyboard, the 2.0 rom will take
; over, but will use the pre-existing 1.3 execbase for Coldcapture
; if it passes the checksum consistancy checks. The ColdCapture
; routine then IDs the OS version. If 1.3, then it returns, if
; 2.0, it then jumps to one of the two CPU routines which reenable the
; MMU and restart 1.3. The near impossible is achievable!
;
; Note that I blast over the ColdCapture vector rather than chaining
; as I am at such a high priority in the boot sequence that no one is
; supposed to be able to get to ColdCapture ahead of me. Now if
; another program blows away Coldcapture, then reboot will not survive
; a hardware reset.
;
_InitRoutine2:
movem.l d0-d7/a0-a6,-(a7) ;Save Registers
move.l ABSEXECBASE,a6 ;Get Execbase
lea.l ColdInit,a0 ;Romtag ColdCapture address
lea.l initDDescrip2,a1 ;Romtag Start Address
suba.l a1,a0 ;length to ColdInit
move.l #$7fc5000,a1 ;Final Start Address of Romtag
add.l a1,a0 ;Add Offset to get Final ColdInit address
move.l a0,ColdCapture(a6) ;Move to ColdCapture
; Recalculate checksum
lea $22(a6),a0
moveq #$16,d0
moveq #0,d1
sumloop2:
add.w (a0)+,d1
dbra d0,sumloop2
not.w d1
move.w d1,$52(a6)
InitExit2:
movem.l (a7)+,d0-d7/a0-a6 ;Restore Registers
rts
ColdInit: ;Remember, we are in Supervisor Mode
;during ColdCapture
movem.l d0-d1/a0,-(a7) ;Save Registers
cmpi.w #$1114,($f80000) ;Test if 2.0
bne ExitCold
bsr _IDCpu ;CPU Type returned in d0
btst.l #AFB_68040,d0
beq.b Do0302 ;Jump to next test if not 040
bra.b My040InitCode2 ;Load code pointer
Do0302:
btst.l #AFB_68030,d0 ;Test for 030
beq.b ExitCold ;Just return if not a 020 or better
Ok0302:
lea.l TC0302(pc),a0
_PMOVE (a0),tc
CNOP 0,4
RB030:
reset
jmp $fc0002 ;Load code pointer
TC0302: DC.L $80f08630
ExitCold:
movem.l (a7)+,d0-d1/a0 ;Restore Registers
jmp (a5) ;Return to OS
My040InitCode2:
moveq #0,d1 ;Clear out VBR, TC, and CACR
_MOVEC d1,vbr
_MOVEC d1,tc
_MOVEC d1,cacr
_CPUSHA040 ;Dump Caches
_PFLUSHA040 ;Clear out ATC
_CINVA040 ;Invalidate caches
move.l #$04fbc040,d1 ;Set up MMU for default memory translation setup
_MOVEC d1,dtt0
move.l #$08f7c040,d1
_MOVEC d1,dtt1
move.l #$04fbc000,d1
_MOVEC d1,itt0
move.l #$08f7c000,d1
_MOVEC d1,itt1
move.l #$7fc6000,d1 ;Write MMU Root table pointer to SRP & URP
_MOVEC d1,srp
_MOVEC d1,urp
_CPUSHA040 ;Dump and Kill caches once again
_PFLUSHA040
_CINVA040
move.w #$C000,d0 ;Load TC and activate the MMU
_MOVEC d0,tc
bra RB030
_IDCpu:
_MOVEC cacr,d1 ; Get the Cache Control Register
move.l #$8000,d0 ; Make a copy
_MOVEC d0,cacr ; Try to set the CACR
_MOVEC cacr,d0 ; Save the real value
_MOVEC d1,cacr ; Restore it
cmpi.l #$8000,d0 ; Check for 040 bit
beq Load040 ; Yup, an 040
moveq #0,d0
bset.l #AFB_68030,d0 ; Must be 020 or 030
rts
Load040:
moveq #0,d0
bset.l #AFB_68040,d0
rts
; this is the name that the module will have
modName2: DC.B 'ReBoot13.romtag ',0
idString2: DC.B 'ReBoot13.romtag 3.31 (10/25/92)',13,10,0
_EndTag2:
;--------------------End of Protected Romtag Space-------------------------------
;
; Move Romtag to $7fc5000 which appears at f05000 via MMU tables
;
@MakeRomTag13:
movem.l d0-d1/a0-a3,-(a7) ;Save Registers
lea.l _EndTag2,a0 ;Romtag End address
lea.l initDDescrip2,a1 ;Romtag Start Address
suba.l a1,a0 ;Romtag length
move.l a0,a3
move.l #$f05000,a2 ;Remapped romtag Start Address
add.l a2,a3 ;Relocated _EndTag2 Address
move.l a0,d0 ;Number of Bytes to copy
move.l #$7fc5000,a0 ;Final Address of Romtag
MRTLoop:
move.b (a1)+,(a0)+ ;Copy romtag to new location
dbra d0,MRTLoop
;
;Patch relocated Romtag
;
move.l a2,($7fc5002) ;New initDDescript2
move.l a3,($7fc5006) ;EndTag2
lea.l modName2,a1 ;Calc New modname after reloc
lea.l initDDescrip2,a3 ;Start of Existing romtag
sub.l a3,a1
add.l a2,a1
move.l a1,($7fc500e) ;Store in RT_NAME
lea.l idString2,a1 ;Calculate loc of new idString2
sub.l a3,a1
add.l a2,a1
move.l a1,($7fc5012) ;Store in RT_IDSTRING
lea.l _InitRoutine2,a1 ;Calc relocated InitRoutine2
sub.l a3,a1
add.l a2,a1
move.l a1,($7fc5016) ;Store in RT_INIT
movem.l (a7)+,d0-d1/a0-a3 ;Restore Registers
rts
end